package game;

import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.Document;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import texture.FileUtil;

public class StitcherPanel {
	private static String WINDOW_TITLE = "Stitcher";
	private static int WIDTH = 1514;
	private static int HEIGHT = 860;
	private static int DIVIDER_LOCATION = 620;

	private Frame mainFrame = new Frame(WINDOW_TITLE);
	public Canvas mainCanvas = new Canvas();
	public JPanel leftPanel = new JPanel();

	public Button stitcherButton;

	public TitledBorder inputTitledBorder;
	public JPanel inputFilePanel;
	public JTextField inputFileNameTextField;
	public JFileChooser inputFileChooser;
	public ImageIcon inputFileChooserButtonIcon;
	public JButton inputFileChooserButton;
	public JTextArea inputFileTextArea;
	public UndoManager undo ;
	public String inputFileOpenButtonName = "inputFileOpenButton";
	public JButton inputFileReloadButton;
	public JButton inputFileSaveButton;

	public TitledBorder outputTitledBorder;
	public JPanel outputFilePanel;
	public JTextField outputFileNameTextField;
	public JFileChooser outputFileChooser;
	public ImageIcon outputFileChooserButtonIcon;
	public JButton outputFileChooserButton;
	public String outputFileOpenButtonName = "outputFileOpenButton";

	public int fileNameTextFieldSize = 42;
	public Dimension fileNameTextFieldDim = new Dimension(360, 28);
	public Dimension fileChooserButtonDim = new Dimension(100, 28);
	
	private StitcherStatus statusTree = StitcherStatus.get();

	public StitcherPanel() {
	}

	public void buildUI() {
		buildLeftPanel();
		buildMainPanel();
		addListeners();
	}

	public void buildMainPanel() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		mainFrame.setLayout(new BorderLayout());

		JScrollPane leftScrollPane = new JScrollPane(leftPanel);
		JScrollPane mainScrollPane = new JScrollPane(mainCanvas);
		JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScrollPane, mainScrollPane);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(DIVIDER_LOCATION);

		// Provide minimum sizes for the two components in the split pane
		Dimension minimumSize = new Dimension(100, 50);
		leftScrollPane.setMinimumSize(minimumSize);
		mainScrollPane.setMinimumSize(minimumSize);

		mainFrame.add(splitPane, BorderLayout.CENTER);

		mainFrame.setMinimumSize(new Dimension(WIDTH, HEIGHT));
		mainFrame.pack();
		mainFrame.setVisible(true);
	}

	public void dispose() {
		mainFrame.dispose();
	}

	private void buildLeftPanel() {
		GridBagLayout layout = new GridBagLayout();
		leftPanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 20, 20));
		leftPanel.setLayout(layout);
		GridBagConstraints c = new GridBagConstraints();

		// input elements
		createInputElements();
		layoutInputElements();
		setInputElementsData();

		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.gridy = 0;
		leftPanel.add(inputFilePanel, c);

		// output elements
		createOutputElements();
		layoutOutputElements();
		setOutputElementsData();

		c.fill = GridBagConstraints.HORIZONTAL;
		c.weighty = 0.4;
		c.gridx = 0;
		c.gridy = 1;
		leftPanel.add(outputFilePanel, c);
	}

	private void createOutputElements() {
		outputTitledBorder = BorderFactory.createTitledBorder("Output File");
		outputFileNameTextField = new JTextField("", fileNameTextFieldSize);
		outputFileNameTextField.setEditable(false);
		outputFileNameTextField.setPreferredSize(fileNameTextFieldDim);
		outputFileChooser = new JFileChooser();
		outputFileChooserButtonIcon = createImageIcon();
		outputFileChooserButton = new JButton("File...");
		outputFileChooserButton.setName(outputFileOpenButtonName);
		outputFileChooserButton.setIcon(outputFileChooserButtonIcon);
		outputFileChooserButton.setPreferredSize(fileChooserButtonDim);
	}

	private void layoutOutputElements() {
		GridBagLayout layout = new GridBagLayout();
		outputFilePanel = new JPanel(layout);
		GridBagConstraints c = new GridBagConstraints();

		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.gridy = 0;
		outputFilePanel.add(outputFileNameTextField, c);

		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 0.5;
		c.gridx = 1;
		c.gridy = 0;
		outputFilePanel.add(outputFileChooserButton, c);

		
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 1;
		c.gridy = 1;
		stitcherButton = new Button("Save Stitcher");
		outputFilePanel.add(stitcherButton, c);
		
		outputFilePanel.setBorder(outputTitledBorder);
	}

	private void setOutputElementsData() {
		String defaultPath = System.getProperty("user.home") + "\\Pictures\\";
		outputFileNameTextField.setText(defaultPath);
	}

	private void createInputElements() {
		inputTitledBorder = BorderFactory.createTitledBorder("Input File");
		inputFileNameTextField = new JTextField("", fileNameTextFieldSize);
		inputFileNameTextField.setEditable(false);
		inputFileNameTextField.setPreferredSize(fileNameTextFieldDim);
		inputFileChooser = new JFileChooser();
		inputFileChooserButtonIcon = createImageIcon();
		inputFileChooserButton = new JButton("File...");
		inputFileChooserButton.setName(inputFileOpenButtonName);
		inputFileChooserButton.setIcon(inputFileChooserButtonIcon);
		inputFileChooserButton.setPreferredSize(fileChooserButtonDim);
		inputFileReloadButton = new JButton("Reload");
		inputFileChooserButton.setPreferredSize(fileChooserButtonDim);
		inputFileSaveButton= new JButton("Save");
		inputFileSaveButton.setPreferredSize(fileChooserButtonDim);
		inputFileTextArea = new JTextArea("");
		undo = new UndoManager();
		inputFileTextArea.setFont( new Font("monospaced", Font.PLAIN,12) );
	}

	private void layoutInputElements() {
		GridBagLayout layout = new GridBagLayout();
		inputFilePanel = new JPanel(layout);
		GridBagConstraints c = new GridBagConstraints();

		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth=3;
		inputFilePanel.add(inputFileNameTextField, c);

		c.gridx = 3;
		c.gridy = 0;
		c.gridwidth=1;
		inputFilePanel.add(inputFileChooserButton, c);
		
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth=2;
		inputFilePanel.add(new JLabel(""), c);
		
		c.gridx = 2;
		c.gridy = 1;
		c.gridwidth=1;
		inputFilePanel.add(inputFileReloadButton, c);

		c.gridx = 3;
		c.gridy = 1;
		c.gridwidth=1;
		inputFilePanel.add(inputFileSaveButton, c);
		
		
		//c.fill = GridBagConstraints.HORIZONTAL;
		c.ipady = 300;
		c.insets = new Insets(10, 0, 0, 0);
		c.gridwidth = 4;
		c.gridx = 0;
		c.gridy = 3;
		JScrollPane scroll = new JScrollPane(inputFileTextArea, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS);
		scroll.setPreferredSize(new Dimension(28, 160));
		inputFilePanel.add(scroll, c);

		inputFilePanel.setBorder(inputTitledBorder);
	}

	private void setInputElementsData() {
		String defaultPath = System.getProperty("user.home");
		defaultPath = defaultPath+"\\workspace2\\M5_V1\\assets\\textures\\blocks\\";
		inputFileNameTextField.setText(defaultPath);
	}

	private static ImageIcon createImageIcon() {
		String path = "./icons/fileChooser.png";
		java.net.URL imgURL = StitcherPanel.class.getResource(path);
		if (imgURL != null) {
			return new ImageIcon(imgURL);
		} else {
			System.err.println("Couldn't find file: " + path);
			return null;
		}
	}

	public void addListeners() {
		mainFrame.addWindowFocusListener(new WindowAdapter() {
			@Override
			public void windowGainedFocus(WindowEvent e) {
				mainCanvas.requestFocusInWindow();
			}
		});

		mainFrame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				statusTree.closeRequestedYN = true;
			}
		});

		stitcherButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				statusTree.outputFileSaveYN = true;
			}
		});

		inputFileChooserButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				File defaultPath = new File(inputFileNameTextField.getText());
				if(defaultPath.isDirectory()){
					inputFileChooser.setCurrentDirectory(defaultPath);
				}else{
					inputFileChooser.setSelectedFile(defaultPath);
				}
				inputFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
				inputFileChooser.setFileFilter(new FileNameExtensionFilter("Txt (*.txt)", "txt"));
				
				int returnVal = inputFileChooser.showOpenDialog(leftPanel);
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File file = inputFileChooser.getSelectedFile();
					inputFileNameTextField.setText(file.getAbsolutePath());
					String s = FileUtil.load(file);
					inputFileTextArea.setText(s);
					statusTree.inputFileText = s;
					statusTree.inputFileChangedYN=true;
				}
			}
		});
		
		inputFileChooser.addChoosableFileFilter(new FileFilter() {
			public String getDescription() {
				return "Txt and PNG (*.txt,*.png)";
			}

			public boolean accept(File f) {
				if (f.isDirectory()) {
					return true;
				} else {
					String fileName=f.getName().toLowerCase();
					return fileName.endsWith(".txt")||fileName.endsWith(".png");
				}
			}
		});

		outputFileChooserButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				File defaultPath = new File(outputFileNameTextField.getText());
				if(defaultPath.isDirectory()){
					outputFileChooser.setCurrentDirectory(defaultPath);
				}else{
					outputFileChooser.setSelectedFile(defaultPath);
				}
				outputFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
				outputFileChooser.setFileFilter(new FileNameExtensionFilter("PNG(*.png)", "png"));
				
				int returnVal = outputFileChooser.showOpenDialog(leftPanel);
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File file = outputFileChooser.getSelectedFile();
					outputFileNameTextField.setText(file.getAbsolutePath());
				}
				
			}
		});
		
		inputFileSaveButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				File currentFile = new File(inputFileNameTextField.getText());
				if (currentFile.isDirectory()) {
					return;
				}

				FileWriter fw = null;
				try {
					String s = inputFileTextArea.getText();
					statusTree.inputFileText = s;
					s= statusTree.getPaddedTextureName();
					inputFileTextArea.setText(s);
					fw = new FileWriter(currentFile);
					fw.write(s);
				} catch (IOException ioe) {
					System.out.println("Exception Caught : " + ioe.getMessage());
				} finally {
					if (fw != null) {
						try {
							fw.close();
						} catch (IOException ioe2) {
						}
					}
				}
			}
		});
		

		Document doc = inputFileTextArea.getDocument();

		doc.addUndoableEditListener(new UndoableEditListener() {
			public void undoableEditHappened(UndoableEditEvent evt) {
				undo.addEdit(evt.getEdit());
			}
		});

		inputFileTextArea.getActionMap().put("Undo", new AbstractAction("Undo") {
			public void actionPerformed(ActionEvent evt) {
				try {
					if (undo.canUndo()) {
						undo.undo();
					}
				} catch (CannotUndoException e) {
				}
			}
		});
		inputFileTextArea.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");
		inputFileTextArea.getActionMap().put("Redo", new AbstractAction("Redo") {
			public void actionPerformed(ActionEvent evt) {
				try {
					if (undo.canRedo()) {
						undo.redo();
					}
				} catch (CannotRedoException e) {
				}
			}
		});
		inputFileTextArea.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
		
	}

	public String getOutputFileName(){
		return outputFileNameTextField.getText();		
	}
}
